package cn.ctbu.xiaopeng.studentscoremanage.api;


import cn.ctbu.xiaopeng.studentscoremanage.pojo.dto.StudentQueryDTO;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.entity.Course;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.entity.Student;
import cn.ctbu.xiaopeng.studentscoremanage.enums.ResultEnum;
import cn.ctbu.xiaopeng.studentscoremanage.exception.ResultException;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.vo.StudentPageVO;
import cn.ctbu.xiaopeng.studentscoremanage.service.ClassesService;
import cn.ctbu.xiaopeng.studentscoremanage.service.DepartmentService;
import cn.ctbu.xiaopeng.studentscoremanage.service.StudentService;
import cn.ctbu.xiaopeng.studentscoremanage.utils.BuildTbSortUtils;
import cn.ctbu.xiaopeng.studentscoremanage.utils.JwtUtils;
import cn.ctbu.xiaopeng.studentscoremanage.utils.PageResultUtils;
import cn.ctbu.xiaopeng.studentscoremanage.utils.ResultUtils;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.vo.page.SortParam;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.dto.PageQueryDTO;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.vo.page.PageResult;
import cn.ctbu.xiaopeng.studentscoremanage.pojo.vo.Result;
import cn.hutool.core.bean.BeanUtil;
import jakarta.servlet.http.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author xiaopeng
 * @version 1.0
 */
@RestController
@RequestMapping("/api/student")
@RequiredArgsConstructor
@Slf4j
public class StudentApiController {

    private final StudentService studentService;

    private final ClassesService classesService;

    private final DepartmentService departmentService;


    /**
     * 查询所有学生信息
     *
     * @return
     */
    @GetMapping("/list")
    public Result<List<Student>> getAllStu() {
        return ResultUtils.success(studentService.getAllStu());
    }


    /**
     * 查询所有学生的不同名称
     * @return
     */
    @GetMapping("/getAllDifferentSName")
    public Result<List<Student>> getAllDifferentSName() {
        // 获取所有课程
        List<Student> allCourses = studentService.getAllStu();

        // 使用 stream 通过课程名称去重，保留 Course 对象
        List<Student> distinctStu = allCourses.stream()
                .filter(distinctByKey(Student::getName))  // 通过课程名称去重
                .collect(Collectors.toList());  // 收集去重后的课程列表

        return ResultUtils.success(distinctStu);
    }

    // 辅助方法：根据课程名称去重
    public static <T> java.util.function.Predicate<T> distinctByKey(
            java.util.function.Function<? super T, ?> keyExtractor) {
        java.util.Set<Object> seen = new java.util.HashSet<>();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 根据id查询学生信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Student> findById(@PathVariable Integer id) {
        return ResultUtils.success(studentService.findById(id));
    }


    /**
     * 根据学生姓名模糊查询学生信息
     *
     * @param name
     * @return
     */
    @GetMapping("/query-name")
    public Result<List<Student>> findByNameStartWith(String name) {
        return ResultUtils.success(studentService.findByNameStartWith(name));
    }

    /**
     * 添加学生
     *
     * @param student
     * @return
     */
    @PostMapping("/add")
    public Result<Student> add(@RequestBody Student student) {
        if (student != null) {
            return ResultUtils.success(studentService.insert(student));
        } else {
            return ResultUtils.error("对象为空！");
        }
    }

    /**
     * 根据id删除学生
     *
     * @param id
     */
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Integer id) {
        studentService.deleteById(id);
        return ResultUtils.success();
    }

    /**
     * 批量删除学生
     *
     * @param idsPath 路径中以逗号分隔的学生ID
     * @return 删除结果
     */
    @DeleteMapping("/delete/batch/{idsPath}")
    public Result deleteStudentByIds(@PathVariable String idsPath) {
        try {
            // 将路径中的逗号分隔字符串解析成 List<Integer>
            List<Integer> ids = Stream.of(idsPath.split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());

            studentService.deleteStudentsByIds(ids);
            return ResultUtils.success("批量删除成功");
        } catch (IllegalArgumentException e) {
            return ResultUtils.error("删除失败：" + e.getMessage());
        } catch (Exception e) {
            return ResultUtils.error("系统异常：" + e.getMessage());
        }
    }

    /**
     * 修改学生信息
     *
     * @param student
     * @return
     */
    @PutMapping("/update")
    public Result update(@RequestBody Student student) {
        if (student != null) {
            return ResultUtils.success(studentService.update(student));
        } else {
            return ResultUtils.error("对象为空！");
        }
    }

    /**
     * 登录校验
     * <p>当用户登录成功，服务器端会创建一个 Session，并将用户的信息存储在这个 Session 中（例如 `userInfo`）。
     * 服务器会生成一个唯一的 `Session ID`（如 `JSESSIONID`），并通过 HTTP 响应头的 `Set-Cookie` 返回给客户端。
     * 浏览器会自动将 `JSESSIONID` 存储在 Cookie 中，每次请求时，浏览器会自动携带这个 `Cookie` 给服务器。
     * 服务器根据 `JSESSIONID` 找到对应的 Session，从而识别用户身份。</p>
     *
     * @param sno
     * @param password
     * @param httpServletRequest
     * @return
     * @throws Exception
     */
    @GetMapping("/validate")
    public Result validateSnoAndPsw(String sno, String password, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Student student = studentService.validateSnoAndPsw(sno, password);
        if (student != null) {  //
            // 法一：将用户信息存入 session (Session + Cookie)
/*            HttpSession session = request.getSession();
            session.setAttribute("userInfo", student-info);

            // 输出 服务器端保存 Session ID 到控制台
            log.info("Session ID: " + session.getId());
            return ResultUtils.success();*/

            // 法二：将用户信息存入 JWT 令牌 (JWT+Cookie)
            //登录成功,生成令牌,下发令牌
            Map<String, Object> claims = new HashMap<>();
            claims.put("sno", student.getSno());
            claims.put("name", student.getName());
            claims.put("id", student.getId());

            String jwt = JwtUtils.generateJwt(claims); //jwt包含了当前登录的学生信息
            //前端（客户端、浏览器）成功登录后获取到对应的jwt令牌并存储到Application下的Local Storage目录中，
            //之后向服务器发出的请求都会自动将该jwt令牌携带到请求头中的的token中。之后再进行校验jwt令牌的有效性。

            log.info("jwt:" + jwt);

            // 设置 JWT 到 HttpOnly Cookie中
            Cookie cookie = new Cookie("token", jwt);
            cookie.setHttpOnly(true); // 防止前端 通过 JS 脚本访问
            cookie.setPath("/"); // 设置路径
            cookie.setMaxAge(86400); // 设置过期时间 24h// （单位：秒）

            // 可使用简化操作：GetCookieWithJwtUtils.generateAndSetJwtCookie(claims,cookieMaxAge);
            response.addCookie(cookie);


            return ResultUtils.success();

            // TODO 使用JWT配合Cookie实现登录校验


        }
        return ResultUtils.error(ResultEnum.LOGIN_ERROR);
    }

    /**
     * 分页查询学生信息,可以实现按照表头排序
     *
     * @param pageQueryDTO
     * @return
     */
    @PostMapping("/page")
    /**
     * 根据页面查询学生信息，支持排序
     *
     * @param pageQueryVO 包含分页和排序信息的查询对象，如果为null，则使用默认分页和排序
     * @return 返回分页后的学生信息和总记录数
     */
    public PageResult getAllStuByPageWithSort(@RequestBody PageQueryDTO<StudentQueryDTO> pageQueryDTO) {
        // 默认分页参数
        int pageIndex = 0;
        int pageSize = 10;

        if (pageQueryDTO == null) {
            // pageQueryVO为空直接走默认分页查询
            Pageable pageable = PageRequest.of(pageIndex, pageSize);
            Page<Student> students = studentService.getAllWithPage(pageable); // 使用默认分页和排序
            return PageResultUtils.success(students.getContent(), students.getTotalElements());
        } else {
            // 根据传入的页码和页面大小初始化分页参数
            pageIndex = pageQueryDTO.getPage() > 0 ? pageQueryDTO.getPage() - 1 : 0;
            pageSize = pageQueryDTO.getLimit();

            // 初始化排序对象
            Sort sort = Sort.unsorted();
            if (pageQueryDTO.getSorts() != null && !pageQueryDTO.getSorts().isEmpty()) {
                // 构建Sort对象，根据前端传入的多个排序参数
                sort = BuildTbSortUtils.buildSort(pageQueryDTO.getSorts());
            } else {
                // 如果没有排序规则，则默认按照id升序排序
                sort = Sort.by(Sort.Direction.ASC, "id");
            }

            // 创建Pageable对象，包含分页和排序信息
            Pageable pageable = PageRequest.of(pageIndex, pageSize, sort);

            if (pageQueryDTO.getData() != null) {
                // 根据传入的学生信息进行查询
                StudentQueryDTO studentQueryDTO = pageQueryDTO.getData();

                // 执行查询
                Page<StudentPageVO> studentPage = studentService.getStudentPageByConditions(studentQueryDTO, pageable);

                // 返回分页结果
                return PageResultUtils.success(BeanUtil.copyToList(studentPage.getContent(), StudentPageVO.class),
                        studentPage.getTotalElements());
            } else {
                // 如果pageQueryVO不为空，但data为空，则抛出异常
                throw new ResultException(ResultEnum.COMMON_ERROR);
            }
        }
    }

}
